﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using Zhp.Common.Appsetting;
using Zhp.Common.Extention;
using Zhp.Common.Helper;
using Zhp.Common.WebApp;
using Zhp.SqlSugar.Entity;
using Zhp.SqlSugar.Repository;
using Zhp.SqlSugar.Trigger.Core;

namespace Zhp.SqlSugar.Extensions
{
    public static class SqlsugarSetup
    {
        private static string DbType = "DbType";
        private static string _connectionStringName = "ConnectionString";

        public static void AddSqlsugarSetup(this IServiceCollection services)
        {
            services.AddSqlsugarSetup(_connectionStringName);
        }

        public static void AddSqlsugarTriggerSetup(this IServiceCollection services)
        {
            services.AddSqlsugarSetup(_connectionStringName, () =>
            {
                //添加触发器功能
                var program = AppSettingHelper.GetOptions<ProgramCodeOptions>();
                var trigger = new TriggerExecute(program.TriggerName);
                services.AddSingleton<ITriggerExecute>(trigger);
            });
        }

        public static void AddSqlsugarTriggerSetup(this IServiceCollection services, string connectionStringName)
        {
            services.AddSqlsugarSetup(connectionStringName, () =>
            {
                //添加触发器功能
                var program = AppSettingHelper.GetOptions<ProgramCodeOptions>();
                var trigger = new TriggerExecute(program.TriggerName);
                services.AddSingleton<ITriggerExecute>(trigger);
            });
        }

        public static void AddSqlsugarSetup(this IServiceCollection services, string connectionStringName, Action triggerAction = null)
        {
            var dbType = AppHelper.Configuration.GetConnectionString(DbType).ToEnum<DbType>();

            services.AddSingleton<ISqlSugarClient>(s => {
                SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
                {
                    DbType = dbType,
                    ConnectionString = AppHelper.Configuration.GetConnectionString(connectionStringName),
                    IsAutoCloseConnection = true,
                    MoreSettings = new ConnMoreSettings()
                    {
                        IsWithNoLockQuery = true,
                        SqlServerCodeFirstNvarchar = true
                    }
                },
                db =>
                {
                    //单例参数配置，所有上下文生效
                    db.Aop.OnLogExecuting = (sql, pars) =>
                    {
                        //Console.WriteLine(sql);//输出sql
                    };
                    db.Aop.OnError = (exp) =>//SQL报错
                    {
                        //获取原生SQL推荐 5.1.4.63  性能OK
                        UtilMethods.GetNativeSql(exp.Sql, new SugarParameter[] { });

                        //获取无参数SQL对性能有影响，特别大的SQL参数多的，调试使用
                        UtilMethods.GetSqlString(dbType, exp.Sql, new SugarParameter[] { });
                    };
                    //监控所有超过1秒的Sql
                    db.Aop.OnLogExecuted = (sql, p) =>
                    {
                        //执行时间超过1秒
                        if (db.Ado.SqlExecutionTime.TotalSeconds > 1)
                        {
                            //代码CS文件名
                            var fileName = db.Ado.SqlStackTrace.FirstFileName;
                            //代码行数
                            var fileLine = db.Ado.SqlStackTrace.FirstLine;
                            //方法名
                            var FirstMethodName = db.Ado.SqlStackTrace.FirstMethodName;
                            //db.Ado.SqlStackTrace.MyStackTraceList[1].xxx 获取上层方法的信息
                        }
                    };

                    //增、删、改事件
                    db.Aop.DataExecuting = DataExecuting;

                    //全局过滤器
                    db.QueryFilter.AddTableFilter<IDeleted>(it => it.IsDeleted == false);
                });
                return sqlSugar; 
            });//这边是SqlSugarScope用AddSingleton

            //触发器功能
            triggerAction?.Invoke();

            services.AddTransient(typeof(IBaseRepository<>), typeof(BaseRepository<>));

        }

        /// <summary>
        /// 增、删、改事件
        /// </summary>
        /// <param name="oldValue"></param>
        /// <param name="entityInfo"></param>
        private static void DataExecuting(object oldValue, DataFilterModel entityInfo)
        {
            //主键自动赋值
            if (entityInfo.EntityColumnInfo.IsPrimarykey)
            {
                if (Nullable.GetUnderlyingType(entityInfo.GetType()) != null)
                {
                    //如果是可空类型
                    if (oldValue == null)
                    {
                        entityInfo.SetValue(SnowFlakeHelper.GetLongId());
                    }
                }
                else
                {
                    var typeName = entityInfo.EntityColumnInfo.PropertyInfo.PropertyType.Name;
                    if (typeName == typeof(string).Name && string.IsNullOrEmpty(oldValue.ToString()))
                    {
                        entityInfo.SetValue(SnowFlakeHelper.GetLongId().ToString());
                    }
                    else if (typeName == typeof(long).Name && Convert.ToInt64(oldValue) == 0)
                    {
                        entityInfo.SetValue(SnowFlakeHelper.GetLongId());
                    }
                    else if (typeName == typeof(Guid).Name && oldValue.ToString() == Guid.Empty.ToString())
                    {
                        entityInfo.SetValue(Guid.NewGuid());
                    }
                }
                return;
            }

            if (entityInfo.EntityValue is IBaseEntity baseEntity)
            {
                SetValue(entityInfo, baseEntity);
            }
            else if (entityInfo.EntityValue is IEnumerable<IBaseEntity> baseEntityList)
            {
                foreach (var item in baseEntityList)
                {
                    SetValue(entityInfo, item);
                }
            }
        }

        private static void SetValue(DataFilterModel entityInfo, IBaseEntity baseEntity)
        {
            var currentUser = ApplicationHelper.GetScopeService<ICurrentUser>();
            switch (entityInfo.OperationType)
            {
                case DataFilterType.InsertByObject:
                    {
                        if (entityInfo.PropertyName == nameof(baseEntity.CreateTime))
                        {
                            entityInfo.SetValue(DateTime.Now);
                        }
                        else if (entityInfo.PropertyName == nameof(baseEntity.CreateBy))
                        {
                            entityInfo.SetValue(currentUser?.UserName);
                        }
                    }
                    break;
                case DataFilterType.UpdateByObject:
                    {
                        if (entityInfo.PropertyName == nameof(baseEntity.UpdateTime))
                        {
                            entityInfo.SetValue(DateTime.Now);
                        }
                        else if (entityInfo.PropertyName == nameof(baseEntity.UpdateBy))
                        {
                            entityInfo.SetValue(currentUser?.UserName);
                        }
                    }
                    break;
                //case DataFilterType.DeleteByObject:
                //    {
                //        baseEntity.UpdateTime = DateTime.Now;
                //        baseEntity.UpdateBy = currentUser?.Name;
                //    }
                //    break;
                default:
                    break;
            }
        }
    }
}
